using Engine;
using Engine.Graphics;

namespace Game
{
    public abstract class Camera
    {
        public GameWidget GameWidget
        {
            get;
            set;
        }

        public abstract Vector3 ViewPosition
        {
            get;
        }

        public abstract Vector3 ViewDirection
        {
            get;
        }

        public abstract Vector3 ViewUp
        {
            get;
        }

        public abstract Vector3 ViewRight
        {
            get;
        }

        public abstract Matrix ViewMatrix
        {
            get;
        }

        public abstract Matrix InvertedViewMatrix
        {
            get;
        }

        public abstract Matrix ProjectionMatrix
        {
            get;
        }

        public abstract Matrix ScreenProjectionMatrix
        {
            get;
        }

        public abstract Matrix InvertedProjectionMatrix
        {
            get;
        }

        public abstract Matrix ViewProjectionMatrix
        {
            get;
        }

        public abstract Vector2 ViewportSize
        {
            get;
        }

        public abstract Matrix ViewportMatrix
        {
            get;
        }

        public abstract BoundingFrustum ViewFrustum
        {
            get;
        }

        public abstract bool UsesMovementControls
        {
            get;
        }

        public abstract bool IsEntityControlEnabled
        {
            get;
        }

        public Camera(GameWidget gameWidget)
        {
            GameWidget = gameWidget;
        }

        public Vector3 WorldToScreen(Vector3 worldPoint, Matrix worldMatrix)
        {
            return new Viewport(0, 0, Window.Size.X, Window.Size.Y).Project(worldPoint, ScreenProjectionMatrix, ViewMatrix, worldMatrix);
        }

        public Vector3 ScreenToWorld(Vector3 screenPoint, Matrix worldMatrix)
        {
            return new Viewport(0, 0, Window.Size.X, Window.Size.Y).Unproject(screenPoint, ScreenProjectionMatrix, ViewMatrix, worldMatrix);
        }

        public virtual void Activate(Camera previousCamera)
        {
        }

        public abstract void Update(float dt);
        public virtual void PrepareForDrawing() { }
    }
}
